package com.sam.java;

import java.util.LinkedList;
import java.util.Random;

/**
 * Created by samwang on 2018/4/21.
 */
public class ProducerConsumer {
    public static void main(String[] args) {
        Storage storage = new Storage();
        Producer producer = new Producer(storage);
        Consumer consumer = new Consumer(storage);
        producer.start();
        consumer.start();
    }
}


// 方法1，wait() / notify()方法
class Storage {
    // 仓库最大存储量
    private final int MAX_SIZE = 10;

    //消费掉这么多个就停止
    private int testCount = 100;

    // 仓库存储的载体
    LinkedList<Object> list = new LinkedList<Object>();
    Random random = new Random();

    // 生产产品
    void produce() {
        synchronized (list) {
            // 如果仓库已满
            while (list.size() == MAX_SIZE) {
                System.out.println("仓库已满，【生产者】： 暂时不能执行生产任务!");
                try {
                    // 由于条件不满足，生产阻塞
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 生产产品
            list.add(new Object());
            System.out.println("【生产者】：生产了一个产品\t【现仓储量为】:" + list.size());
            list.notifyAll();
        }
    }

    // 消费产品
    public void consume() {
        synchronized (list) {
            //如果仓库存储量不足
            while (list.size() == 0) {
                System.out.println("仓库已空，【消费者】： 暂时不能执行消费任务!");
                try {
                    // 由于条件不满足，消费阻塞
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            list.remove();
            testCount--;
            System.out.println("【消费者】：消费了一个产品\t【现仓储量为】:" + list.size());
            list.notifyAll();
        }
    }

    public int randomTime() {
        return Math.abs(random.nextInt(200));
    }

}

class Producer extends Thread
{
    private Storage storage;
    private int testCount = 100;


    public Producer(Storage storage)
    {
        this.storage = storage;
    }

    @Override
    public void run()
    {
        while (true) {
            storage.produce();
            testCount--;
            if (testCount == 0) {
                break;
            }
            try {
                Thread.sleep(storage.randomTime()); //模拟生产需要的时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer extends Thread {
    private Storage storage;
    private int testCount = 100;


    public Consumer(Storage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        while (true) {
            storage.consume();
            testCount--;
            if (testCount <= 0 && storage.list.isEmpty()) {
                break;
            }
            try {
                Thread.sleep(storage.randomTime()); //模拟消费需要的时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


//方法2